home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
mpeg_play-2.1
/
gdith.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
24KB
|
1,026 lines
/*
* gdith.c --
*
* Procedures dealing with grey-scale and mono dithering,
* as well as X Windows set up procedures.
*
*/
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include <math.h>
#include "video.h"
#include "proto.h"
#include "dither.h"
#include <sys/time.h>
/* Range values for lum, cr, cb. */
int LUM_RANGE;
int CR_RANGE;
int CB_RANGE;
/* Array that remaps color numbers to actual pixel values used by X server. */
unsigned char pixel[256];
unsigned long wpixel[256];
/* Arrays holding quantized value ranged for lum, cr, and cb. */
int *lum_values;
int *cr_values;
int *cb_values;
/* Declaration of global variable containing dither type. */
extern int ditherType;
extern int matched_depth;
/* Structures used by the X server. */
Display *display;
static XImage *ximage = NULL;
static Colormap cmap;
static Window window;
static GC gc;
/* Frame Rate Info */
extern int framerate;
/* Video rates table */
/* Cheat on Vid rates, round to 30, and use 30 if illegal value
Except for 9, where Xing means 15, and given their popularity, we'll
be nice and do it */
static int VidRateNum[16]={30, 24, 24, 25, 30, 30, 50, 60,
60, 15, 30, 30, 30, 30, 30, 30};
/* Luminance and chrominance lookup tables */
static double *L_tab, *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
/*
*--------------------------------------------------------------
*
* InitColor --
*
* Initialize lum, cr, and cb quantized range value arrays.
* Also initializes the lookup tables for the possible
* values of lum, cr, and cb.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
InitColor()
{
int i, CR, CB;
L_tab = (double *)malloc(LUM_RANGE*sizeof(double));
Cr_r_tab = (double *)malloc(CR_RANGE*sizeof(double));
Cr_g_tab = (double *)malloc(CR_RANGE*sizeof(double));
Cb_g_tab = (double *)malloc(CB_RANGE*sizeof(double));
Cb_b_tab = (double *)malloc(CB_RANGE*sizeof(double));
if (gammaCorrectFlag) {
for (i=0; i<LUM_RANGE; i++) {
lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
L_tab[i] = 1.164 * (lum_values[i] - 16.0);
L_tab[i] = (pow(L_tab[i] / 255.0, (1 / gammaCorrect)) * 255.0) + 0.5;
}
} else {
for (i=0; i<LUM_RANGE; i++) {
lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
L_tab[i] = 1.164 * (lum_values[i] - 16.0);
}
}
for (i=0; i<CR_RANGE; i++) {
cr_values[i] = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
Cr_r_tab[i] = 1.366 * (cr_values[i] - 128.0);
Cr_g_tab[i] = -0.700 * (cr_values[i] - 128.0);
}
for (i=0; i<CB_RANGE; i++) {
cb_values[i] = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
Cb_g_tab[i] = -0.334 * (cb_values[i] - 128.0);
Cb_b_tab[i] = 1.732 * (cb_values[i] - 128.0);
}
}
/*
*--------------------------------------------------------------
*
* ConvertColor --
*
* Given a l, cr, cb tuple, converts it to r,g,b.
*
* Results:
* r,g,b values returned in pointers passed as parameters.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
ConvertColor(l, cr, cb, r, g, b)
unsigned int l, cr, cb;
unsigned char *r, *g, *b;
{
double fl, fcr, fcb, fr, fg, fb;
/*
* Old method w/o lookup table
*
* fl = 1.164*(((double) l)-16.0);
* fcr = ((double) cr) - 128.0;
* fcb = ((double) cb) - 128.0;
*
* fr = fl + (1.366 * fcr);
* fg = fl - (0.700 * fcr) - (0.334 * fcb);
* fb = fl + (1.732 * fcb);
*/
fl = L_tab[l];
fr = fl + Cr_r_tab[cr];
fg = fl + Cr_g_tab[cr] + Cb_g_tab[cb];
fb = fl + Cb_b_tab[cb];
if (fr < 0.0) fr = 0.0;
else if (fr > 255.0) fr = 255.0;
if (fg < 0.0) fg = 0.0;
else if (fg > 255.0) fg = 255.0;
if (fb < 0.0) fb = 0.0;
else if (fb > 255.0) fb = 255.0;
*r = (unsigned char) fr;
*g = (unsigned char) fg;
*b = (unsigned char) fb;
}
#ifdef SH_MEM
int gXErrorFlag = 0;
int HandleXError(dpy, event)
Display *dpy;
XErrorEvent *event;
{
gXErrorFlag = 1;
return 0;
}
int HandleXError();
void InstallXErrorHandler()
{
XSetErrorHandler(HandleXError);
XFlush(display);
}
void DeInstallXErrorHandler()
{
XSetErrorHandler(NULL);
XFlush(display);
}
#endif
/*
*--------------------------------------------------------------
*
* ResizeDisplay --
*
* Resizes display window.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void ResizeDisplay(w, h)
unsigned int w, h;
{
if (ditherType == NO_DITHER || ditherType == PPM_DITHER) return;
XResizeWindow(display, window, w, h);
XFlush(display);
}
/*
*--------------------------------------------------------------
*
* MakeWindow --
*
* Create X Window
*
* Results:
* Read the code.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
#ifdef SH_MEM
int CompletionType = -1;
#endif
static int
MakeWindow(name)
char *name;
{
XSizeHints hint;
unsigned int fg, bg;
char *hello = "MPEG Play";
int screen;
Window CreateFullColorWindow();
XVisualInfo vinfo;
if ((ditherType == NO_DITHER) || (ditherType == PPM_DITHER)) return;
display = XOpenDisplay(name);
if (display == NULL) {
fprintf(stderr, "Can not open display\n");
exit(-2);
}
#ifdef SH_MEM
if(shmemFlag)
CompletionType = XShmGetEventBase(display) + ShmCompletion;
#endif
screen = DefaultScreen (display);
/* Fill in hint structure */
hint.x = 200;
hint.y = 300;
hint.width = 150;
hint.height = 150;
hint.flags = PPosition | PSize;
/* Get some colors */
bg = WhitePixel (display, screen);
fg = BlackPixel (display, screen);
/* Make the window */
if (ditherType == FULL_COLOR_DITHER || ditherType == FULL_COLOR2_DITHER) {
window = CreateFullColorWindow (display, hint.x, hint.y, hint.width, hint.height);
if (window == 0) {
fprintf (stderr, "-color option only valid on full color display\n");
exit (-1);
}
} else {
if (((XMatchVisualInfo (display, screen, 24, TrueColor, &vinfo) != 0) ||
(XMatchVisualInfo (display, screen, 24, DirectColor, &vinfo) != 0)) &&
(!quietFlag)) {
printf("\nOn 24 bit displays: use -dither color to get full color\n\t\tordered dither is the default.\n");
}
if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
window = XCreateSimpleWindow (display,
DefaultRootWindow (display),
hint.x, hint.y,
hint.width, hint.height,
4, fg, bg);
matched_depth = 1;
} else {
Visual *vis;
XSetWindowAttributes attrib;
unsigned long attrib_flags=0;
if (!XMatchVisualInfo (display, screen, matched_depth = 8, PseudoColor,
&vinfo)) {
if (ditherType != GRAY_DITHER && ditherType != GRAY2_DITHER &&
ditherType != GRAY256_DITHER && ditherType != GRAY2562_DITHER) {
fprintf(stderr, "specified dither requires 8 bit display\n");
return 0;
} else if (!XMatchVisualInfo(display, screen, matched_depth = 32,
GrayScale, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 24,
GrayScale, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 16,
GrayScale, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 8,
GrayScale, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 32,
TrueColor, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 24,
TrueColor, &vinfo) &&
!XMatchVisualInfo(display, screen, matched_depth = 16,
TrueColor, &vinfo)) {
fprintf(stderr, "- -dither gray requires at least 8 bit display\n");
exit(-1);
}
}
vis=vinfo.visual;
if (XDefaultDepthOfScreen(XDefaultScreenOfDisplay(display)) != 8) {
attrib_flags |= CWColormap;
attrib.colormap = XCreateColormap(display, DefaultRootWindow(display),
vis, AllocNone);
owncmFlag = TRUE;
}
attrib.background_pixel = bg;
attrib.border_pixel = fg;
attrib.backing_store = NotUseful;
attrib.save_under = False;
attrib.background_pixel = bg;
attrib.border_pixel = bg;
attrib_flags |= CWBackPixel | CWBorderPixel | CWBackingStore | CWSaveUnder;
window = XCreateWindow (display,
DefaultRootWindow (display),
hint.x, hint.y,
hint.width, hint.height, 4,
matched_depth, InputOutput, vis,
attrib_flags, &attrib);
}}
XSelectInput(display, window, StructureNotifyMask);
/* Tell other applications about this window */
XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint);
/* Map window. */
XMapWindow(display, window);
/* Wait for map. */
while(1) {
XEvent xev;
XNextEvent(display, &xev);
if(xev.type == MapNotify && xev.xmap.event == window)
break;
}
XSelectInput(display, window, NoEventMask);
return TRUE;
}
/*
*--------------------------------------------------------------
*
* InitDisplay --
*
* Initialized display, sets up colormap, etc.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void InitDisplay(name)
char *name;
{
int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
XColor xcolor;
int i, lum_num, cr_num, cb_num;
unsigned char r, g, b;
Colormap dcmap;
if ((ditherType == NO_DITHER) || (ditherType == PPM_DITHER)) return;
if (noDisplayFlag) return;
if (!MakeWindow(name)) {
/* Could not do that dither. Try again if can */
switch (ditherType) {
case HYBRID_DITHER:
case HYBRID2_DITHER:
case FS4_DITHER:
case FS2_DITHER:
case FS2FAST_DITHER:
case Twox2_DITHER:
case ORDERED_DITHER:
case ORDERED2_DITHER:
case MBORDERED_DITHER:
fprintf(stderr, "trying -dither color\n");
ditherType = FULL_COLOR_DITHER;
InitColorDisplay(name);
InitColorDither(matched_depth == 32);
return;
case GRAY_DITHER:
case GRAY2_DITHER:
case GRAY256_DITHER:
case GRAY2562_DITHER:
case FULL_COLOR_DITHER:
case FULL_COLOR2_DITHER:
case MONO_DITHER:
case MONO_THRESHOLD:
default:
/* cant do anything */
exit(-1);
}
}
gc = XCreateGC(display, window, 0, 0);
dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
xcolor.flags = DoRed | DoGreen | DoBlue;
if (owncmFlag) goto create_map;
retry_alloc_colors:
for (i=0; i<ncolors; i++) {
lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
cr_num = (i / CB_RANGE)%CR_RANGE;
cb_num = i % CB_RANGE;
ConvertColor(lum_num, cr_num, cb_num, &r, &g, &b);
xcolor.red = r * 256;
xcolor.green = g * 256;
xcolor.blue = b * 256;
if (XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
int j;
unsigned long tmp_pixel;
XWindowAttributes xwa;
if (!quietFlag) {
fprintf(stderr, "Using private colormap.\n");
}
/* Free colors. */
for(j = 0; j < i; j ++) {
tmp_pixel = wpixel[j];
XFreeColors(display, cmap, &tmp_pixel, 1, 0);
}
create_map:
XGetWindowAttributes(display, window, &xwa);
cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
XSetWindowColormap(display, window, cmap);
goto retry_alloc_colors;
}
pixel[i] = xcolor.pixel;
wpixel[i] = xcolor.pixel;
}
ximage = NULL;
}
/*
*--------------------------------------------------------------
*
* InitGrayDisplay --
*
* Initialized display for gray scale dither.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void InitGrayDisplay(name)
char *name;
{
int ncolors = 128;
XColor xcolor;
int i;
Colormap dcmap;
unsigned long tmp_pixels[256];
MakeWindow(name);
gc = XCreateGC(display, window, 0, 0);
dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
xcolor.flags = DoRed | DoGreen | DoBlue;
if (owncmFlag) goto create_map;
retry_alloc_grays:
for (i=0; i<ncolors; i++) {
xcolor.red = (i*2) * 256;
xcolor.green = (i*2) * 256;
xcolor.blue = (i*2) * 256;
if(XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
int j;
XWindowAttributes xwa;
if (!quietFlag) {
fprintf(stderr, "Using private colormap.\n");
}
/* Free colors. */
for(j = 0; j < i; j ++) {
unsigned long tmp_pixel;
tmp_pixel = tmp_pixels[j*2];
XFreeColors(display, cmap, &tmp_pixel, 1, 0);
}
create_map:
XGetWindowAttributes(display, window, &xwa);
cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
XSetWindowColormap(display, window, cmap);
goto retry_alloc_grays;
}
tmp_pixels[i*2] = pixel[i*2] = xcolor.pixel;
tmp_pixels[(i*2)+1] = pixel[(i*2)+1] = xcolor.pixel;
wpixel[(i*2)] = xcolor.pixel;
wpixel[(i*2)+1] = xcolor.pixel;
if(matched_depth == 8) {
wpixel[i*2] |= wpixel[i*2] << 8;
wpixel[i*2+1] |= wpixel[i*2+1] << 8;
}
if(matched_depth == 8 || matched_depth == 16) {
wpixel[i*2] |= wpixel[i*2] << 16;
wpixel[i*2+1] |= wpixel[i*2+1] << 16;
}
#ifdef SIXTYFOUR_BIT
if(matched_depth == 8 || matched_depth == 16 || matched_depth == 24 || matched_depth == 32) {
wpixel[i*2] |= wpixel[i*2] << 32;
wpixel[i*2+1] |= wpixel[i*2+1] << 32;
}
#endif
}
ximage = NULL;
}
/*
*--------------------------------------------------------------
*
* InitGray256Display --
*
* Initialized display for gray scale dither with 256 levels
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void InitGray256Display(name)
char *name;
{
int ncolors = 256;
XColor xcolor;
int i;
Colormap dcmap;
int result;
XWindowAttributes xwa;
unsigned long tmp_pixels[256];
MakeWindow(name);
gc = XCreateGC(display, window, 0, 0);
dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
xcolor.flags = DoRed | DoGreen | DoBlue;
if (owncmFlag) {
XGetWindowAttributes(display, window, &xwa);
cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
XSetWindowColormap(display, window, cmap);
}
retry_alloc_grays:
for (i=0; i<ncolors; i++) {
xcolor.red = i * 256;
xcolor.green = i * 256;
xcolor.blue = i * 256;
if((result=XAllocColor(display, cmap, &xcolor)) == 0 && cmap == dcmap) {
int j;
unsigned long tmp_pixel;
if (!quietFlag) {
fprintf(stderr, "Using private colormap.\n");
}
/* Free colors. */
for(j = 0; j < i; j ++) {
tmp_pixel = tmp_pixels[j];
XFreeColors(display, cmap, &tmp_pixel, 1, 0);
}
XGetWindowAttributes(display, window, &xwa);
cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
XSetWindowColormap(display, window, cmap);
goto retry_alloc_grays;
}
tmp_pixels[i] = pixel[i] = xcolor.pixel;
wpixel[i] = xcolor.pixel;
if(matched_depth == 8) wpixel[i] |= wpixel[i] << 8;
if(matched_depth == 8 || matched_depth == 16) {
wpixel[i] |= wpixel[i] << 16;
}
#ifdef SIXTYFOUR_BIT
if(matched_depth == 8 || matched_depth == 16 || matched_depth == 24 || matched_depth == 32) {
wpixel[i] |= wpixel[i] << 32;
}
#endif
}
ximage = NULL;
}
/*
*--------------------------------------------------------------
*
* InitMonoDisplay --
*
* Initialized display for monochrome dither.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void InitMonoDisplay(name)
char *name;
{
XGCValues xgcv;
MakeWindow(name);
xgcv.background = BlackPixel(display, DefaultScreen(display));
xgcv.foreground = WhitePixel(display, DefaultScreen(display));
gc = XCreateGC(display, window, GCForeground | GCBackground, &xgcv);
ximage = NULL;
}
/*
*--------------------------------------------------------------
*
* InitColorDisplay --
*
* Initialized display for full color output.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void InitColorDisplay(name)
char *name;
{
XWindowAttributes winattr;
MakeWindow(name);
gc = XCreateGC(display, window, 0, 0);
ximage = NULL;
XGetWindowAttributes(display, window, &winattr);
/*
* Misuse of wpixel
*/
wpixel[0] = winattr.visual->red_mask;
wpixel[1] = winattr.visual->green_mask;
wpixel[2] = winattr.visual->blue_mask;
}
/*
*--------------------------------------------------------------
*
* ExecuteDisplay --
*
* Actually displays display plane in previously created window.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
ExecuteDisplay(vid_stream)
VidStream *vid_stream;
{
char dummy;
Visual *FindFullColorVisual();
Visual *fc_visual;
int depth;
static int rate_deal = -1;
static int one_frame_time;
static struct timeval tftarget, tfnow;
register int usec, sec;
totNumFrames++;
if (partialFlag) {
if ((endFrame != -1) && (totNumFrames > endFrame)) {
#ifdef ANALYSIS
PrintAllStats();
#endif
PrintTimeInfo();
if (loopFlag) {
clear_data_stream(&vid_stream->buf_start,
&vid_stream->max_buf_length,
&vid_stream->buf_length,
&vid_stream->buffer);
longjmp(env, 1);
}
DestroyVidStream(curVidStream);
exit(0);
}
if (totNumFrames < startFrame) {
return;
}
}
/* Do frame rate control */
switch (rate_deal) {
case 0:
break;
default:
gettimeofday(&tfnow, (struct timezone *)NULL);
usec = tftarget.tv_usec - tfnow.tv_usec;
sec = tftarget.tv_sec - tfnow.tv_sec;
if (usec < 0) {
usec += 1000000;
sec--;
}
/* If we're not behind, wait a bit */
if ((sec >= 0) && usec > 0) {
tfnow.tv_sec = sec;
tfnow.tv_usec = usec;
select(0, NULL, NULL, NULL ,&tfnow);
gettimeofday(&tfnow, (struct timezone *)NULL);
}
/* Setup target for next frame */
tftarget.tv_usec = tfnow.tv_usec + one_frame_time;
if (tftarget.tv_usec >= 1000000) {
tftarget.tv_usec -= 1000000;
tftarget.tv_sec = tfnow.tv_sec + 1;
} else tftarget.tv_sec = tfnow.tv_sec;
break;
case -1:
switch (framerate) {
case -1: /* Go with stream Value */
rate_deal = VidRateNum[vid_stream->picture_rate];
gettimeofday(&tftarget, (struct timezone *)NULL);
one_frame_time = 1000000 / rate_deal;
break;
case 0: /* as fast as possible */
rate_deal = 0;
break;
default:
rate_deal = framerate;
gettimeofday(&tftarget, (struct timezone *)NULL);
one_frame_time = 1000000 / rate_deal;
break;
}
break;
}
if (!quietFlag) {
fprintf (stderr, "%d\r", totNumFrames);
}
if (requireKeypressFlag) {
char foo;
printf("Press return (%d) ",totNumFrames);
while ((foo=getchar())!='\n');
}
if (ditherType == NO_DITHER) return;
if (ditherType == PPM_DITHER) {
ExecutePPM(vid_stream);
return;
}
if (!noDisplayFlag) {
if (ximage == NULL) {
int pixels_per_mb = 16;
if(IS_2x2_DITHER(ditherType)) pixels_per_mb = 32;
if ((ditherType == FULL_COLOR_DITHER) ||
(ditherType == FULL_COLOR2_DITHER)) {
int w, h;
w = vid_stream->mb_width * pixels_per_mb;
h = vid_stream->mb_height * pixels_per_mb;
fc_visual = FindFullColorVisual(display, &depth);
ximage = XCreateImage (display, fc_visual, depth, ZPixmap,
0, &dummy, w, h, 32, 0);
} else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
ximage = XCreateImage (display, None, matched_depth, XYBitmap, 0, &dummy,
vid_stream->mb_width * pixels_per_mb,
vid_stream->mb_height * pixels_per_mb, 8, 0);
ximage->byte_order = MSBFirst;
ximage->bitmap_bit_order = MSBFirst;
} else {
ximage = XCreateImage(display, None, matched_depth, ZPixmap, 0, &dummy,
vid_stream->mb_width * pixels_per_mb,
vid_stream->mb_height * pixels_per_mb, 8, 0);
}
}
/*
* Always work in native bit and byte order. This tells Xlib to reverse
* bit and byte order if necessary when crossing a network. Frankly, this
* part of XImages is somewhat underdocumented, so this may not be exactly
* correct.
*/
#ifdef LITTLE_ENDIAN_ARCHITECTURE
ximage->byte_order = LSBFirst;
ximage->bitmap_bit_order = LSBFirst;
#else
ximage->byte_order = MSBFirst;
ximage->bitmap_bit_order = MSBFirst;
#endif
#ifdef SH_MEM
if (shmemFlag) {
XShmPutImage(display, window, gc, vid_stream->current->ximage,
0, 0, 0, 0,
vid_stream->current->ximage->width,
vid_stream->current->ximage->height, True);
XFlush(display);
while(1) {
XEvent xev;
XNextEvent(display, &xev);
if (xev.type == CompletionType) {
break;
}
}
}
else
#endif
{
ximage->data = (char *) vid_stream->current->display;
XPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
}
}
}
extern char *inputName;
extern char *strrchr();
#define PPM_BITS 8
/*
*--------------------------------------------------------------
*
* ExecutePPM --
*
* Write out a display plane as a PPM file.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
ExecutePPM(vid_stream)
VidStream *vid_stream;
{
static int munged = 0;
static char mungedInputName[300];
char fileName[300];
FILE *file;
int n;
unsigned int *p;
unsigned int r, g, b;
if (!munged) {
char *cp;
cp = strrchr(inputName, '/');
if (cp != NULL)
++cp;
else
cp = inputName;
strcpy(mungedInputName, cp);
cp = strrchr(mungedInputName, '.');
if (cp != NULL)
*cp = '\0';
munged = 1;
}
sprintf(fileName, "%s_%05d.ppm", mungedInputName, totNumFrames );
file = fopen(fileName, "w");
if (file == NULL) {
perror(fileName);
exit(1);
}
fprintf(file, "P6\n");
fprintf(file, "%d %d\n", vid_stream->h_size, vid_stream->v_size);
fprintf(file, "255\n");
p = (unsigned int *) vid_stream->current->display;
n = vid_stream->h_size * vid_stream->v_size;
while (n > 0) {
r = *p & 0xff;
g = (*p >> PPM_BITS) & 0xff;
b = (*p >> (2*PPM_BITS)) & 0xff;
putc(r, file);
putc(g, file);
putc(b, file);
++p;
--n;
}
fclose(file);
}